<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>

    <h1>为何</h1>
    <p>抵消每次获取资源产生的消耗，这种池的设计会初始预设资源,跟池有关的特征包括：池子的初始值、最大值、活跃值等</p>
    <h1>线程池什么时候触发拒绝策略</h1>
    <p>
        一般是超过池的最大值时触发，但线程连接池还有一个阻塞队列缓冲区，当前提交任务数大于（maxPoolSize + queueCapacity）时就会触发线程池的拒绝策略了。
    </p>

    <h1>线程池有哪几种拒绝策略</h1>
        <h2>
            接口
            RejectedExecutionHandler
            rejectedExecution
            方法实现拒绝策略
        </h2>
    <ul>
        <li>CallerRunPolicy(<span style="color:red;">扔给调用者,自己不去执行</span>)</li>
        <li>AbortPolicy(<span  style="color:red;">取消</span>)</li>
        <li>DiscardPolicy(<span style="color:red;">直接抛弃,最新的</span>)</li>
        <li>DiscardOldestPolicy(<span style="color:red;">直接抛弃,最旧的</span>)</li>
    </ul>
    <ul>
        <li>
            <pre>
                public static class CallerRunsPolicy implements RejectedExecutionHandler {

                    public CallerRunsPolicy() { }

                    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
                        if (!e.isShutdown()) {
                            r.run();
                        }
                    }
                }
            </pre>
        </li>
        <li>
            <pre>
                public static class AbortPolicy  implements RejectedExecutionHandler {

                    public AbortPolicy () { }

                    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
                         throw new RejectedExecutionException("Task " + r.toString() +
                                                 " rejected from " +
                                                 e.toString());
                    }
                }
            </pre>
        </li>
        <li>
            <pre>
                public static class DiscardPolicy   implements RejectedExecutionHandler {
                    // 没使用，就是超出了就不管
                    public DiscardPolicy () { }

                    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
                    }
                }
            </pre>
        </li>
        <li>
            <pre>
                public static class DiscardOldestPolicy implements RejectedExecutionHandler {

                    public DiscardOldestPolicy() { }

                    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
                        if (!e.isShutdown()) {
                            e.getQueue().poll();
                            e.execute(r);
                        }
                    }
                }
            </pre>
        </li>
    </ul>


    <p>阿里有自己的策略</p>
    <pre>
        public class AbortPolicyWithReport extends ThreadPoolExecutor.AbortPolicy {

            protected static final Logger logger = LoggerFactory.getLogger(AbortPolicyWithReport.class);

            private final String threadName;

            private final URL url;

            private static volatile long lastPrintTime = 0;

            private static Semaphore guard = new Semaphore(1);

            public AbortPolicyWithReport(String threadName, URL url) {
                this.threadName = threadName;
                this.url = url;
            }

            @Override
            public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
                String msg = String.format("Thread pool is EXHAUSTED!" +
                                " Thread Name: %s, Pool Size: %d (active: %d, core: %d, max: %d, largest: %d), Task: %d (completed: %d)," +
                                " Executor status:(isShutdown:%s, isTerminated:%s, isTerminating:%s), in %s://%s:%d!",
                        threadName, e.getPoolSize(), e.getActiveCount(), e.getCorePoolSize(), e.getMaximumPoolSize(), e.getLargestPoolSize(),
                        e.getTaskCount(), e.getCompletedTaskCount(), e.isShutdown(), e.isTerminated(), e.isTerminating(),
                        url.getProtocol(), url.getIp(), url.getPort());
                logger.warn(msg);
                dumpJStack();
                throw new RejectedExecutionException(msg);
            }

            private void dumpJStack() {
               //省略实现
            }
        }
    </pre>
</body>
</html>